package com.example.controller;

import com.example.job.JobTask;
import com.example.utils.IDUtils;
import org.redisson.api.*;
import org.redisson.api.listener.ListAddListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

import java.time.Duration;
import java.util.concurrent.*;

@RestController
public class TestRedissonController implements CommandLineRunner {

    Logger logger = LoggerFactory.getLogger(getClass());

    public static final String NAME = "XX_NAME";

    public static final String MAP = "XX_MAP";

    public static final String RMapCache_MAP = "XX_RMapCache_MAP";

    private ThreadPoolExecutor threadPoolExecutor;

    @Resource
    private RedissonClient redissonClient;

    /***
     * 数据共享器
     * @return
     */
    @RequestMapping(value = "getRAtomicLong")
    public RAtomicLong getRAtomicLong() {
        return redissonClient.getAtomicLong(NAME);
    }


    /***
     * 计数器新增
     * @return
     */
    @RequestMapping(value = "getCompareAndSet")
    public long getCompareAndSet() {
        RAtomicLong longObject = redissonClient.getAtomicLong(NAME);
        return longObject.incrementAndGet();
    }


    /***
     * 分布式MAP新增
     * @return
     */
    @RequestMapping(value = "addMap")
    public String addMap() {
        String uuid = IDUtils.getId();
        RMap map = redissonClient.getMap(MAP);
        map.put(uuid, uuid);
        return uuid;
    }

    /***
     * 分布式MAP删除
     * @param key
     * @return
     */
    @RequestMapping(value = "delMap")
    public Object delMap(String key) {
        RMap map = redissonClient.getMap(MAP);
        return map.remove(key);
    }

    /***
     * 分布式MAP缓存新增
     * @return
     */
    @RequestMapping(value = "addRMapCache")
    public Object addRMapCache() {
        String uuid = IDUtils.getId();
        RMapCache rMapCache = redissonClient.getMapCache(RMapCache_MAP);
        rMapCache.put(uuid, uuid, 10, TimeUnit.SECONDS);
        return uuid;
    }


    /***
     * 分布式MAP缓存删除
     * @param key
     * @return
     */
    @RequestMapping(value = "delRMapCache")
    public Object delRMapCache(String key) {
        RMapCache rMapCache = redissonClient.getMapCache(RMapCache_MAP);
        return rMapCache.remove(key);
    }


    /***
     * 分布式SET新增
     * @param
     * @return
     * */
    @RequestMapping(value = "addSet")
    public String addSet() {
        String uuid = IDUtils.getId();
        RSet<Object> zset = redissonClient.getSet("Zset");
        zset.add(uuid);
        return uuid;
    }

    /***
     * 分布式SET删除
     * @param
     * @return
     * */
    @RequestMapping(value = "addLIst")
    public String addLIst() {
        String uuid = IDUtils.getId();
        RList<Object> list = redissonClient.getList("ZList");
        list.add(uuid);
        return uuid;
    }


    /***
     * 分布式LIST新增
     * @param
     * @return
     * */
    @RequestMapping(value = "getLIst")
    public void getLIst() {
        RList<String> list = redissonClient.getList("ZList");
        for (String key : list) {
            logger.warn(key);
        }
    }

    /***
     * 分布式LIST删除
     * @param
     * @return
     ***/
    @RequestMapping(value = "addQueue")
    public String addQueue() {
        String uuid = IDUtils.getId();
        RBlockingQueue<Object> zQueue = redissonClient.getBlockingQueue("ZQueue");
        zQueue.add(uuid);
        return uuid;
    }

    /****
     * 设置一个延时任务
     * @param id 任务id
     * @param time 延时时间
     * @return
     */
    @RequestMapping(value = "setDelayWork")
    public String setDelayWork(String id, int time) {
        logger.warn("setDelayWork id:{},time:{}", id, time);
        RScheduledExecutorService executorService = redissonClient.getExecutorService("myExecutor");
        return executorService.schedule(id, new JobTask(), Duration.ofSeconds(time)).getTaskId();
    }

    /***
     * 创建一个定时任务
     * @param id 任务id
     * @return
     */
    @RequestMapping(value = "setTask")
    public String setTask(String id) {
        RScheduledExecutorService executorService = redissonClient.getExecutorService("myExecutor");
        return executorService.schedule(id, new JobTask(), CronSchedule.of("*/5 * * * * ?")).getTaskId();
    }

    /***
     * 取消一个定时任务`
     * @param id 任务id
     * @return
     */
    @RequestMapping(value = "cancelTask")
    public Boolean cancelTask(String id) {
        return redissonClient.getExecutorService("myExecutor").cancelTask(id);
    }

    /***
     * 写一个方法获取这个任务最后的执行时间
     * @param id
     * @return
     */
    public long getTaskTime(String id){
        return 0;
    }

    /****
     * 创建一个分布式闭锁
     *
     * @return
     */
    @RequestMapping(value = "tryLatch")
    public String tryLatch() throws Exception {
        RCountDownLatch countDownLatch = redissonClient.getCountDownLatch("XZZZZZ");
        countDownLatch.trySetCount(1);
        countDownLatch.await();
        return "success";
    }

    /****
     * 释放一个分布式闭锁
     *
     * @return
     */
    @RequestMapping(value = "releaseLatch")
    public String releaseLatch() {
        RCountDownLatch countDownLatch = redissonClient.getCountDownLatch("XZZZZZ");
        countDownLatch.countDown();
        return "success";
    }

    @Override
    public void run(String... args) throws Exception {
        this.threadPoolExecutor = new ThreadPoolExecutor(10, 20, 60, TimeUnit.SECONDS, new LinkedBlockingQueue());
        redissonClient.getMap(MAP).addListener(new DeletedObjectListener() {
            @Override
            public void onDeleted(String name) {
                logger.warn("map onDeleted :" + name);
            }
        });
        redissonClient.getList("ZList").addListener(new ListAddListener() {
            @Override
            public void onListAdd(String name) {
                logger.warn("list onListAdd :" + name);
            }
        });
        RBlockingQueue<Object> zQueue = redissonClient.getBlockingQueue("ZQueue");
        this.threadPoolExecutor.execute(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    Object take =   zQueue.poll();
                    if (take != null){
                        threadPoolExecutor.execute(new Runnable() {
                            @Override
                            public void run() {
                                logger.warn("消费消息: " + take);
                            }
                        });
                    }
                }
            }
        });
    }
}